(defun my-move-line-up (p)                  ;;向上移动本行
   "move current line up"
   (interactive "p")
   (let ((c (current-column)))
     (beginning-of-line)
     (kill-line 1)
     (previous-line p)
     (beginning-of-line)
     (yank)
     (previous-line 1)
     (move-to-column c)))

(defun my-move-line-down (p)                ;;向下移动本行
   "move current line down"
   (interactive "p")
   (let ((c (current-column)))
     (beginning-of-line)
     (kill-line 1)
     (next-line p)
     (beginning-of-line)
     (yank)
     (previous-line 1)
     (move-to-column c)))

(defun my-dup-line-down ()                  ;;复制本行到下一行
   "duplicate this line at next line"
   (interactive)
   (let ((c (current-column)))
     (beginning-of-line)
     (ue-select-line-down)
     (beginning-of-line)
     (yank)
     (previous-line 1)
     (move-to-column c)))

(defvar ue-selection-last-point nil
   "Indicates whether to kill-append or kill-new")
(defvar ue-selection-total-lines 0
   "Total number of lines appended so far to the last item in kill-ring")

(defun ue-selection-update-cont ()
   "Update `ue-selection-last-point' variable"
   (if (and this-command
            (string= (format "%s" this-command)
                     "ue-select-line-down-continued"))
       (setq ue-selection-last-point (point))
     (setq ue-selection-total-lines 0)
     (setq ue-selection-last-point  nil)))

(add-hook 'post-command-hook 'ue-selection-update-cont)

(defun ue-select-line-down-continued ()     ;;连续复制多行
   "like Shift+down in UltraEdit, but do no selection.
Just put these continuous lines all toghether as a new item in kill-ring.
Messages will appear in minibuffer telling you how many lines were copied.
Continuous commands with no interruption append new lines to the item.
Any non-ue-select-line-down-continued command will stop gathering new lines
and make a new item in kill-ring.

post-command-hook is used in detecting the continuity of this command.
check `ue-selection-update-cont' and `post-command-hook'."
   (interactive)
   (let ((s (point)))
     (setq next-line-add-newlines t)
     (next-line 1)
     (setq next-line-add-newlines nil)
     (if (and ue-selection-last-point
              (= (save-excursion
                   (when (> (count-lines (point-min) (point)) 1)
                     (previous-line 1))
                   (point))
                 ue-selection-last-point))
         (progn
           (kill-append (buffer-substring s (point)) nil)
           (setq ue-selection-total-lines (1+ ue-selection-total-lines))
           (message (format "%s lines copied" ue-selection-total-lines)))
       (kill-new (buffer-substring s (point)))
       (message "1 line copied")
       ;; some errors will cause post-command-hook deletion
       ;; so add-hook every time after we add the first line
       (add-hook 'post-command-hook 'ue-selection-update-cont)
       (setq ue-selection-total-lines 1))))

(defun ue-select-line-down ()
   "like Shift+down in UltraEdit."
   (interactive)
   (let ((s (point)))
   (setq next-line-add-newlines t)
   (next-line 1)
   (setq next-line-add-newlines nil)
   (kill-new (buffer-substring s (point)))))

(global-set-key   [C-S-up]        'my-move-line-up)
(global-set-key   [C-S-down]      'my-move-line-down)
;(global-set-key   [C-M-down]      'my-dup-line-down)
(global-set-key   [S-down]        'ue-select-line-down-continued)

(global-set-key   [M-down]      'my-dup-line-down)



(defun qiang-comment-dwim-line (&optional arg)
  "Replacement for the comment-dwim command. If no region is selected and current line is not blank and we are not at the end of the line, then comment current line. Replaces default behaviour of comment-dwim, when it inserts comment at the end of the line."
  (interactive "*P")
  (comment-normalize-vars)
  (if (and (not (region-active-p)) (not (looking-at "[ \t]*$")))
      (comment-or-uncomment-region (line-beginning-position) (line-end-position))
    (comment-dwim arg)))
(global-set-key "\M-;" 'qiang-comment-dwim-line)
;========================================智能复制  code by afa311

(defadvice kill-line (before check-position activate)
  (if (member major-mode
              '(emacs-lisp-mode scheme-mode lisp-mode
                                c-mode c++-mode objc-mode js-mode
                                latex-mode plain-tex-mode))
      (if (and (eolp) (not (bolp)))
          (progn (forward-char 1)
                 (just-one-space 0)
                 (backward-char 1)))))
 
(defadvice kill-ring-save (before slick-copy activate compile)
  "When called interactively with no active region, copy a single line instead."
  (interactive (if mark-active (list (region-beginning) (region-end))
                 (message "Copied line")
                 (list (line-beginning-position)
                       (line-beginning-position 2)))))
 
(defadvice kill-region (before slick-cut activate compile)
  "When called interactively with no active region, kill a single line instead."
  (interactive
   (if mark-active (list (region-beginning) (region-end))
     (list (line-beginning-position)
           (line-beginning-position 2)))))
 
;; Copy line from point to the end, exclude the line break
(defun do-copy-line (arg)
  "Copy lines (as many as prefix argument) in the kill ring"
  (interactive "p")
  (kill-ring-save (point)
                  (line-end-position))
                  ;; (line-beginning-position (+ 1 arg)))
  (message "%d line%s copied" arg (if (= 1 arg) "" "s")))
 
(global-set-key (kbd "C-M-k") 'do-copy-line)
;========================================智能复制 结束+++++++++++++++++++++++++++++

;;========================================括号匹配

;; 这是一个很小的函数。你是不是觉得 Emacs 在匹配的括号之间来回跳转的时 候按 C-M-f 和 C-M-b 太麻烦了？vi的 % 就很方便，我们可以把 % 设置为匹配 括号。可是你想输入 % 怎么办呢？

;; 一个很巧妙的解决方案就是，当 % 在括号上按下时，那么匹配括号，否则输 入一个 %。你只需要在 .emacs 文件里加入这些东西就可以达到目的：


(global-set-key "%" 'match-paren)
          
(defun match-paren (arg)
  "Go to the matching paren if on a paren; otherwise insert %."
  (interactive "p")
  (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
	((looking-at "\\s\)") (forward-char 1) (backward-list 1))
	(t (self-insert-command (or arg 1)))))

;;======================================括号匹配结束
;;===================================== 临时记号

;; 有时你需要跳到另一个文件进行一些操作，然后很快的跳回来。你当然可以 使用 bookmark 或者寄存器。但是这些实在是太慢了。你多想拥有vi那样的 ma, mb, 'a, 'b 的操作。现在你可以用几行 elisp 达到类似的目的：

(global-set-key [(control ?\.)] 'ska-point-to-register)
(global-set-key [(control ?\,)] 'ska-jump-to-register)
(defun ska-point-to-register()
  "Store cursorposition _fast_ in a register. 
Use ska-jump-to-register to jump back to the stored 
position."
  (interactive)
  (setq zmacs-region-stays t)
  (point-to-register 8))

(defun ska-jump-to-register()
  "Switches between current cursorposition and position
that was stored with ska-point-to-register."
  (interactive)
  (setq zmacs-region-stays t)
  (let ((tmp (point-marker)))
        (jump-to-register 8)
        (set-register 8 tmp)))
;;===================================== 临时记号结束

;;===================================== go-to-char = vi fx

(defun f-go-to-char (n char)
  "Move forward to Nth occurence of CHAR.
Typing `wy-go-to-char-key' again will move forwad to the next Nth
occurence of CHAR."
  (interactive "p\ncGo to char: ")
  (search-forward (string char) nil nil n)
  (while (char-equal (read-char)
		     char)
    (search-forward (string char) nil nil n))
  (setq unread-command-events (list last-input-event)))

(define-key global-map (kbd "C-c f") 'f-go-to-char)
;;===================================== go-to-char = vi fx ==============

;;===================================== 自动增加 括号。。等右边部分 然后光标定位在当中

(add-hook 'c-mode-hook 'hs-minor-mode)
(defun my-c-mode-auto-pair ()
  (interactive)
  (make-local-variable 'skeleton-pair-alist)
  (setq skeleton-pair-alist  '(
    (?` ?` _ "''")
    (?\( ?  _ " )")
    (?\[ ?  _ " ]")
    (?{ \n > _ \n ?} >)))
  (setq skeleton-pair t)
  (local-set-key (kbd "(") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd "{") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd "`") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd "[") 'skeleton-pair-insert-maybe))
(add-hook 'c-mode-hook 'my-c-mode-auto-pair)


;; (defvar skeleton-pair-cond-alist)
;; (defvar skeleton-pair-alist)
;; (setq skeleton-pair-cond-alist
;;   '(
;;     ;; 前面有 = ，花括号不换行
;;     ((char-bf ?=) . (?\{ _ "}"))
;;     ((or (char-bf ?/)(char-bf ?=)) . (?\[ n _ n "]"))
;;     ;; 行首是/ ，扩展为块注释
;;     ((bolp) . (?/ "*" n _ n "*/"))
;;     (t . (?/))
;;     ;; 前面是 = ， .变为->
;;     ((char-bf ?=) . (?. -1 "->"))
;;     (t . (?.))
;;     ))

;; (defadvice skeleton-pair-insert-maybe (around xxx activate)
;;   (let ((skeleton-pair-alist skeleton-pair-alist)
;;         (x skeleton-pair-cond-alist))
;;     (while
;;         (and
;;          x
;;          (null
;;           (if (and
;;                (eq last-command-event (cadr (car x)))
;;                (eval (caar x)))
;;               (setq skeleton-pair-alist (list (cdar x)))
;;             nil)))
;;       (setq x (cdr x)))
;;     ad-do-it))
;; (defun char-bf (x)
;;   (let ((x (if (listp x) x (list x))))
;;     (save-excursion
;;       (skip-chars-backward " \t")
;;       (memq (char-before (point)) x))))

;; ;;;###autoload
;; (defun skeleton-pair-alist-update ()
;;   (interactive)
;;   (mapcar
;;    (lambda(x)
;;      (define-key (current-local-map)
;;        (eval `(kbd ,(char-to-string (cadr x))))
;;        'skeleton-pair-insert-maybe))
;;    skeleton-pair-cond-alist))
;; ;; (skeleton-pair-alist-update)(defadvice skeleton-pair-insert-maybe (around xxx activate)
;; (let ((skeleton-pair-alist skeleton-pair-alist)
;;       (x skeleton-pair-cond-alist))
;;   (while
;;       (and
;;        x
;;        (null
;;         (if (and
;;              (eq last-command-event (cadr (car x)))
;;              (eval (caar x)))
;;             (setq skeleton-pair-alist (list (cdar x)))
;;           nil)))
;;     (setq x (cdr x)))
;;   ad-do-it))



;; (defun char-bf (x)
;;   (let ((x (if (listp x) x (list x))))
;;     (save-excursion
;;       (skip-chars-backward " \t")
;;       (memq (char-before (point)) x))))

;; ;;;###autoload
;; (defun skeleton-pair-alist-update ()
;;   (interactive)
;;   (mapcar
;;    (lambda(x)
;;      (define-key (current-local-map)
;;        (eval `(kbd ,(char-to-string (cadr x))))
;;        'skeleton-pair-insert-maybe))
;;    skeleton-pair-cond-alist))
;; ;; (skeleton-pair-alist-update)

;;===================================== 自动增加 括号。。等右边部分 然后光标定位在当中
;; for myself?
(defun ins-dot ()
  (interactive)
  (self-insert-command 1)
  (insert " "))
;(local-set-key (kbd ",") 'ins-dot)


;;增加一些exe的环境变量

(when os:windowsp
  (mapc #'add-to-exec-path
        (reverse 
         (list
          (if os:win64p
              "C:/Program Files (x86)/Git/bin"
            "C:/Program Files/Git/bin")
          	"~/.emacs.d/extra-bin/gtags"
            "~/.emacs.d/extra-bin/gnuwin32"
            "~/.emacs.d/extra-bin/unix-utils-bin"
          	"~/bin"))))

(provide 'init-myfunc)
